/**
 * 合并props
 * @template A, B
 * @param props A
 * @param defaultProps B
 * @returns {A & B}
 */
import { AnyObj } from '../common/AnyObj';

export function mergeProps<A extends object, B extends A>(props: A, defaultProps: B,): A & B {
  return { ...defaultProps, ...props };
}

/**
 * 添加属性到某个函数或对象中
 * @param ret
 * @param props
 * @returns
 */
export function attachProperty<A, B extends object>(ret: A, props: B): A & B {
  const obj = ret as AnyObj;
  for (const key in props) {
    obj[key] = props[key];
  }
  return obj as A & B;
}

export function formatDate(date, isObj?: boolean) {
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, '0');
  const day = String(date.getDate()).padStart(2, '0');
  const hours = String(date.getHours()).padStart(2, '0');
  const minutes = String(date.getMinutes()).padStart(2, '0');
  const seconds = String(date.getSeconds()).padStart(2, '0');

  return isObj ? {
    year,
    month,
    day,
    hours,
    minutes,
    seconds
  } : `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}

export function getBarSize(size: any): { width: number | string, height: number | string } {
  return size?.width !== undefined || size?.height !== undefined ? size : { width: size, height: size }
}

export function findMaxLevelAndData<OptionItem extends object>(options: OptionItem[],
  childrenKey: string = 'children'): [number, OptionItem[][]] {

  function calculateLevel(option: OptionItem, currentLevel: number, dataByLevel: OptionItem[][]): number {
    // 如果当前层级不存在于数据数组中，则添加一个新的数组来存储该层级的数据
    if (dataByLevel.length <= currentLevel) {
      dataByLevel.push([]);
    }

    // 将当前节点添加到对应层级的数据数组中
    dataByLevel[currentLevel].push(option);

    // 当前节点的层级
    let level = currentLevel;

    // 如果有子节点，则递归计算子节点的层级，并取最大值
    if (option[childrenKey] && option[childrenKey].length > 0) {
      for (const child of option[childrenKey]) {
        level = Math.max(level, calculateLevel(child, currentLevel + 1, dataByLevel));
      }
    }

    return level;
  }

  // 初始层级为1，因为根节点算作第一层
  let maxLevel = 1;

  // 创建一个空数组来存储每一层的数据
  const dataByLevel: OptionItem[][] = [];

  // 遍历所有根节点，找到最大层级并填充数据
  for (const option of options) {
    maxLevel = Math.max(maxLevel, calculateLevel(option, 0, dataByLevel));
  }

  // 因为我们从0开始计数层级，所以最大层级应该是实际的最大层级+1
  maxLevel += 1;

  return [maxLevel, dataByLevel];
}

export function getArrByCondition<Item>(arr: Item[], conditionFn: (item: Item, index: number) => boolean) {
  return arr?.filter((item: Item, index: number) => conditionFn?.(item, index))
}